package com.edison.demo.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author edison
 */
@Configuration
@EnableAsync
public class ThreadPoolConfig {

    @Value("${thread.core.count}")
    private  int coreCount;
    @Value("${thread.max.count}")
    private int maxPoolSize;
    @Value("${thread.queue.capacity}")
    private int queueCapacity;
    @Value("${thread.keep.alive.seconds}")
    private int keepAliveSeconds;
    @Value("${thread.name.prefix}")
    private String threadNamePrefix;


    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //	•	CPU-bound tasks: Perform intensive calculations (e.g., encryption, data processing).
        //	•	Recommended: Thread Pool Size ≈ Number of CPU Cores.        // 	•	I/O-bound tasks: Involve waiting for external resources (e.g., HTTP requests, file I/O, database queries).
        //	•	Recommended: Thread Pool Size ≈ 2 × Number of CPU Cores (or more, since threads wait on I/O).
        //  •   Optimal Thread Pool Size = Number of Cores * (1 + (Wait Time / Compute Time))
        executor.setCorePoolSize(coreCount);
        // Maximum pool size,
        executor.setMaxPoolSize(maxPoolSize);
        // 	Tune queue size: Start with a moderate size (e.g., 50).
        executor.setQueueCapacity(queueCapacity);
        // Idle threads die after 60s
        executor.setKeepAliveSeconds(keepAliveSeconds);

        executor.setThreadNamePrefix(threadNamePrefix);
        // Use safe rejection policy
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}
